package org.jeecg.modules.ncmeapis.network.utils;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class FileChunkUtil {

    public static String getFileExtension(String fileName) {
        int index = fileName.lastIndexOf(".");
        if (index == -1) return "";
        return fileName.substring(index);
    }

    /**
     * 获取总切片数
     *
     * @param file      源文件
     * @param chunkSize 每个切片大小
     * @return 切片数
     */
    public static int getTotalChunks(File file, int chunkSize) throws Exception {
        try {
            long length = file.length();
            return (int) (length / chunkSize);
        } catch (Exception e) {
            throw new Exception("FileChunkUtil.getTotalChunks()异常 ", e);
        }
    }

    /**
     * 获取单个切片文件
     *
     * @param originFile 源文件
     * @param targetFile 目标切片文件
     * @param chunkSize  每个切片大小
     * @param index      第几个切片
     */
    public static void writeOneSplitFile(File originFile, File targetFile, int chunkSize, int index) throws Exception {
        try {
            //待读文件
            RandomAccessFile in = new RandomAccessFile(originFile, "r");
            //目标文件
            RandomAccessFile out = new RandomAccessFile(targetFile, "rw");
            //开始切割⽂件
            long beginFend = (index) * chunkSize;
            long endFend = (index < getTotalChunks(originFile, chunkSize) - 1 ? (index + 1) * chunkSize : originFile.length()) - 1;
            //申明具体每⼀⽂件的字节数组
            byte[] buffer = new byte[1024];
            int n;
            //从指定位置读取⽂件字节流
            in.seek(beginFend);
            //判断⽂件流读取的边界
            while (in.getFilePointer() <= endFend && (n = in.read(buffer)) != -1) {
                out.write(buffer, 0, n);    //从指定每⼀份⽂件的范围，写⼊不同的⽂件
            }
            //关闭输⼊流
            in.close();
            //关闭输出流
            out.close();
        } catch (Exception e) {
            throw new Exception("FileChunkUtil.getOneSplitFile()异常 ", e);
        }
    }

    /**
     * 将文件切片
     *
     * @param originFile 源文件
     * @param chunkSize  每个切片大小
     * @param path       输出路径文件夹，输出文件名称默认为： 原文件名_index（index为切片索引，从0开始）
     * @return 切片文件数组
     */
    public static File[] getAllChunks(File originFile, int chunkSize, String path) throws Exception {
        try {
            File targetDir = new File(path);
            if (!targetDir.exists()) targetDir.mkdirs();
            int totalChunks = getTotalChunks(originFile, chunkSize);
            File[] chunkFiles = new File[totalChunks];
            for (int i = 0; i < totalChunks; i++) {
                File chunkFile = new File(path + File.separator + originFile.getName() + "_" + i);
                if (chunkFile.exists()) chunkFile.delete();
                chunkFile.createNewFile();

                writeOneSplitFile(originFile, chunkFile, chunkSize, i);
                chunkFiles[i] = chunkFile;
            }
            return chunkFiles;
        } catch (Exception e) {
            throw new Exception(originFile.getPath() + "文件切片失败", e);
        }
    }

    /**
     * ⽂件合并
     *
     * @param targetFile 合并后的目标⽂件
     * @param chunkFiles 切片文件数组
     */
    public static void merge(File targetFile, File[] chunkFiles, boolean isClearTmp) {
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(targetFile, "rw");
            //开始合并⽂件，对应切⽚的⼆进制⽂件
            for (File chunkFile : chunkFiles) {
                //读取切⽚⽂件
                RandomAccessFile reader = new RandomAccessFile(chunkFile, "r");
                byte[] b = new byte[1024];
                int n;
                while ((n = reader.read(b)) != -1) {
                    raf.write(b, 0, n);//⼀边读，⼀边写
                }
                reader.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();

                if (isClearTmp) {
                    for (File chunkFile : chunkFiles) {
                        boolean delete = chunkFile.delete();
                        int i = 0;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}